package com.ruoyi.auth.service;

import com.ruoyi.auth.api.model.dto.UserLoginInfoDto;
import com.ruoyi.auth.integration.IntegrationAuthentication;
import com.ruoyi.auth.integration.IntegrationAuthenticationContext;
import com.ruoyi.auth.integration.authenticator.IntegrationAuthenticator;
import com.ruoyi.common.core.enums.UserStatus;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.config.properties.SecurityProperties;
import com.ruoyi.common.security.domain.LoginUser;
import com.ruoyi.common.security.exception.RuoyiSecurityException;
import com.ruoyi.common.security.utils.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 用户信息处理
 *
 * @author ruoyi
 */
@Service
public class UserDetailsServiceImpl implements CustomUserDetailsService {
    private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);



    @Autowired
    public RedisService redisService;

    @Autowired
    public SecurityProperties securityProperties;

    @Autowired
    public UserLoginInfoServiceImpl userLoginInfoServiceImpl;

//    private Map<String, IUserLoginInfoApiService>  authUserApiServiceMap=new HashMap<>();

    private List<IntegrationAuthenticator> authenticators;

    @Autowired(required = false)
    public void setIntegrationAuthenticators(List<IntegrationAuthenticator> authenticators) {
        this.authenticators = authenticators;
    }

    private String userCategory;

    // userCategory 用户类目   system(系统)  user(会员) merchant（商户）
/*    IUserLoginInfoApiService getUserApiService(String userCategory){
        userCategory=userCategory==null?"system":userCategory;
        this.userCategory = userCategory;
        if(authUserApiServiceMap.get(userCategory)!=null){
            return authUserApiServiceMap.get(userCategory);
        }else {
            ReferenceConfig<IUserLoginInfoApiService> reference = new ReferenceConfig<IUserLoginInfoApiService>();
            // 弱类型接口名
            reference.setInterface(IUserLoginInfoApiService.class);
            //设置分组
            reference.setGroup(userCategory);
            reference.setCheck(false);
            IUserLoginInfoApiService genericService = reference.get();
            authUserApiServiceMap.put(userCategory,genericService);
            return authUserApiServiceMap.get(userCategory);
        }
    }*/

    @Override
    public UserDetails loadUserByUsername(String username) {
        return loadUserByUsername(username, "system");
    }

    @Override
    public UserDetails loadUserByUsername(String username, String userCategory) throws UsernameNotFoundException {
        userCategory = userCategory == null ? "system" : userCategory;
        this.userCategory = userCategory;
        /*userCategory=userCategory==null?"system":userCategory;
        this.userCategory = userCategory;
        UserLoginInfoDto userLoginInfo = userLoginInfoServiceImpl.getUserApiService(userCategory).getUserInfo(username);*/

        IntegrationAuthentication integrationAuthentication = IntegrationAuthenticationContext.get();
        //判断是否是集成登录
        if (integrationAuthentication == null) {
            integrationAuthentication = new IntegrationAuthentication();
        }
        integrationAuthentication.setUsername(username);
        try {
            UserLoginInfoDto userLoginInfo = this.authenticate(integrationAuthentication);
            checkUser(userLoginInfo, username);
            return getUserDetails(userLoginInfo);
        } catch (Exception e) {
            throw e;
        }
    }

    public void checkUser(UserLoginInfoDto userLoginInfo, String username) {
        LoginUser loginUser = null;
        if(username==null || username.equals("")){
            if(!StringUtils.isNull(userLoginInfo)){
                username = userLoginInfo.getUserName();
            }else{
                username = "未知";
            }
        }
        if(StringUtils.isNull(userLoginInfo)){
            try {
                loginUser = new LoginUser(userCategory, null, username, "", null, true, true, true, true,
                        new ArrayList<>());
            }catch (Exception e){
                log.error("模拟用户信息失败:",e);
            }

        }else{
            loginUser = new LoginUser(userCategory, userLoginInfo.getUserId(), username, userLoginInfo.getPassword(), userLoginInfo.getExt(), true, true, true, true,
                    new ArrayList<>());
        }
        SecurityUtils.loginUserLocal.set(loginUser);
        if (StringUtils.isNull(userLoginInfo)) {
            log.info("登录用户：{} 不存在.", username);
            throw new RuoyiSecurityException(RuoyiSecurityException.RUOYI_SECURITY_USER_NOT_FOUND).
                    setBusinessMessage("对不起，您的账号：" + username + " 不存在");
        } else if (UserStatus.DELETED.getCode().equals(userLoginInfo.getDelFlag())) {
            log.info("登录用户：{} 已被删除.", username);
            throw new RuoyiSecurityException(RuoyiSecurityException.RUOYI_SECURITY_USER_DELETED).
                    setBusinessMessage("对不起，您的账号：" + username + " 已被删除");
        } else if (UserStatus.DISABLE.getCode().equals(userLoginInfo.getStatus())) {
            log.info("登录用户：{} 已被停用.", username);
            throw new RuoyiSecurityException(RuoyiSecurityException.RUOYI_SECURITY_USER_STOP_USING).
                    setBusinessMessage("对不起，您的账号：" + username + " 已停用");
        } else if (UserStatus.NOT_ACTIVE.getCode().equals(userLoginInfo.getStatus())) {
            log.info("登录用户：{} 未激活.", username);
            throw new RuoyiSecurityException(RuoyiSecurityException.RUOYI_SECURITY_USER_NOT_ACTIVE).
                    setBusinessMessage("对不起，您的账号：" + username + " 未激活");
        }
    }

    private UserDetails getUserDetails(UserLoginInfoDto userLoginInfo) {
        Set<String> dbAuthsSet = new HashSet<String>();
        if (StringUtils.isNotEmpty(userLoginInfo.getRoles())) {
            // 获取角色
            dbAuthsSet.addAll(userLoginInfo.getRoles());
        }

        if (StringUtils.isNotEmpty(userLoginInfo.getPermissions())) {
            // 获取权限
            dbAuthsSet.addAll(userLoginInfo.getPermissions());
        }
        //如果是空的话设置一个:符号 否则如果为空值的话后面使用会报错
        if (dbAuthsSet.isEmpty()) {
            dbAuthsSet.add(":");
        }

        Collection<? extends GrantedAuthority> authorities = AuthorityUtils
                .createAuthorityList(dbAuthsSet.toArray(new String[0]));
        LoginUser loginUser = new LoginUser(userCategory, userLoginInfo.getUserId(), userLoginInfo.getUserName(), userLoginInfo.getPassword(), userLoginInfo.getExt(), true, true, true, true,
                authorities);
        SecurityUtils.loginUserLocal.set(loginUser);
        return loginUser;
    }

    private UserLoginInfoDto authenticate(IntegrationAuthentication integrationAuthentication) {
        if (this.authenticators != null) {
            for (IntegrationAuthenticator authenticator : authenticators) {
                if (authenticator.support(integrationAuthentication)) {
                    return authenticator.authenticate(integrationAuthentication);
                }
            }
        }
        return null;
    }


}
